package com.pi.shisan.test.receiver;

import com.pi.shisan.test.util.DefaultFont8x8;
import com.pi4j.wiringpi.Gpio;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import java.util.List;

import static com.pi4j.wiringpi.Gpio.HIGH;
import static com.pi4j.wiringpi.Gpio.LOW;
import static com.pi4j.wiringpi.Gpio.OUTPUT;
import static com.pi4j.wiringpi.Gpio.digitalWrite;
import static com.pi4j.wiringpi.Gpio.pinMode;
import static com.pi4j.wiringpi.Gpio.wiringPiSetup;

public class ReceiverDecoder extends ByteToMessageDecoder {

    private static boolean isInit = false;
    private static int allSize = 0;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> list) throws Exception {
        int type = in.readShort();
        int len = in.readShort();
        if (type == 1) {
            //TODO 建立连接
            ctx.channel().writeAndFlush((short)2);
            ctx.channel().writeAndFlush((short)0);
        } else if (type == 0) {
            //TODO 关闭连接
            ctx.channel().close();
        } else if (type == 2) {
            //TODO 初始化
            System.out.println("setup");
            wiringPiSetup();
            ctx.channel().writeAndFlush((short)1);
            ctx.channel().writeAndFlush((short)0);
        } else if (type == 3) {
            //TODO 初始化
            int g = in.readInt();
            int mode = in.readInt();
            System.out.println("pin data:"+g+" / "+mode);
            pinMode(g,mode);
            ctx.channel().writeAndFlush((short)1);
            ctx.channel().writeAndFlush((short)0);
        } else if (type == 4){
            //接收数据
            int addr = in.readInt();
            int data = in.readInt();
            System.out.println("write data:"+addr+" / "+data);
            digitalWrite(addr,data);
            ctx.channel().writeAndFlush((short)1);
            ctx.channel().writeAndFlush((short)0);
        } else if (type == 5) {
            if ((len & 7) != 0) {
                ctx.channel().writeAndFlush((short)0);
                ctx.channel().writeAndFlush((short)0);
                return;
            }
            int size = len/8;
            if (!isInit) {
                allSize = size;
                isInit = true;
                wiringPiSetup();
                pinMode(DIN,OUTPUT);
                pinMode(CS,OUTPUT);
                pinMode(CLK,OUTPUT);

                digitalWrite(CS, LOW);
                for (int i = 0; i < size; i++) {
                    writeData(0x09,0x00);
                }
                digitalWrite(CS, HIGH);
                digitalWrite(CS, LOW);
                for (int i = 0; i < size; i++) {
                    writeData(0x0a,0x01);
                }
                digitalWrite(CS, HIGH);
                digitalWrite(CS, LOW);
                for (int i = 0; i < size; i++) {
                    writeData(0x0b,0x07);
                }
                digitalWrite(CS, HIGH);
                digitalWrite(CS, LOW);
                for (int i = 0; i < size; i++) {
                    writeData(0x0c,0x01);
                }
                digitalWrite(CS, HIGH);
                digitalWrite(CS, LOW);
                for (int i = 0; i < size; i++) {
                    writeData(0xff,0x00);
                }
                digitalWrite(CS, HIGH);
            }

            long []all = new long[size];
            for (int i = 0; i < all.length; i++) {
                all[i]=in.readLong();
            }
            int index = 0;
            byte[][] data = new byte[size][8];
            for (int i = 0; i < size; i++) {
                data[i] = DefaultFont8x8.getPoints(all[index]);
                index ++;
            }
            for (int j = 1; j <= 8; j++) {
                digitalWrite(CS, LOW);
                for (int i = 0; i < size; i++) {
                    writeData(j, data[i][j-1]);
                }
                digitalWrite(CS, HIGH);
            }
            ctx.channel().writeAndFlush((short)1);
            ctx.channel().writeAndFlush((short)0);
        } else if (type == 6) {
            digitalWrite(CS, LOW);
            for (int i = 0; i < allSize; i++) {
                digitalWrite(0x0c,0x00);
            }
            digitalWrite(CS, HIGH);
            ctx.channel().writeAndFlush((short)1);
            ctx.channel().writeAndFlush((short)0);
        } else if (type == 7) {
            digitalWrite(CS, LOW);
            for (int i = 0; i < allSize; i++) {
                digitalWrite(0x0c,0x01);
            }
            digitalWrite(CS, HIGH);
            ctx.channel().writeAndFlush((short)1);
            ctx.channel().writeAndFlush((short)0);
        }
    }

    private static final int CS = 11, CLK = 14, DIN = 12;
    private static final byte[] NONE_POINT = new byte[]{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};

    private void writeData(int addr, int data) {
        writeByte(addr);
        writeByte(data);
        digitalWrite(CLK,HIGH);
    }

    private void writeByte(int data) {
        for (int i = 0; i < 8; i++) {
            digitalWrite(CLK, LOW);
            digitalWrite(DIN, (data & 0x80) == 0 ? LOW : HIGH);
            digitalWrite(CLK, HIGH);
            data <<= 1;
        }
    }
}
